#import "FlexyCubeView.h"
#import "Thinker.h"
#import <appkit/NXImage.h>
#import <appkit/Panel.h>
#import <dpsclient/wraps.h>
#import <libc.h>
#import <math.h>

#import "FlexyCubeWraps.h"

#define ACCELERATION	1.15
#define FLEXY  0.5

#define CUBESIZE	150
#define MINSPEED	1

@implementation FlexyCubeView

- drawSelf:(const NXRect *)rects :(int)rectCount
{
	if (!rects || !rectCount) return self;
	[super drawSelf:rects :rectCount];
	[self drawCube: 1.0];
	return self;
}

- drawCube: (float) gray
{
	float x, y, w, h;

	x = imageRect.origin.x;
	y = imageRect.origin.y;
	w = imageRect.size.width;
	h = imageRect.size.height;

	if (x < 0.0) {
		w += x;
		x = 0.0;
	} else if (x + w > bounds.size.width)
		w = bounds.size.width - x;

	if (y < 0.0) {
		h += y;
		y = 0.0;
	} else if (y + h > bounds.size.height)
		h = bounds.size.height - y;

	// Avoid leaving border smudges
	x += 1; y += 1; w -= 2; h -= 2;

	if (w <= 0 || h <= 0)
	// Ugh, this won't do.
		return self;

	PSgsave();
	PStranslate(x, y);

	drawNeXTCube(w, h, gray);

	PSgrestore();

	return self;
}

- adjustSpeed: (float *) speedp
	minSpeed: (float) minSpeed
	maxSpeed: (float) maxSpeed
	pos: (float *) posp
	iMin: (float) iMin
	iMax: (float) iMax
{
	float speed = *speedp;
	float pnt = *posp;

	if (pnt < iMin)
	{
		if (speed < 0)
			speed /= ACCELERATION;
		else
			speed *= ACCELERATION;
	}
	else if (pnt > iMax)
	{
		if (speed > 0)
		{
			speed /= ACCELERATION;
		}
		else
			speed *= ACCELERATION;
	}
	else if (fabs(speed) < maxSpeed)
		speed *= ACCELERATION;
	else if (fabs(speed) > maxSpeed)
		speed /= ACCELERATION;

	// Change direction when we start going too slowly
	if (fabs(speed) < minSpeed)
		speed = -speed;

	pnt += speed;

	*posp = pnt;
	*speedp = speed;

	return self;
}

- oneStep
{
	static int xCount = 100, yCount = 150;
	
	NXPoint iMin, iMax;
	float x, y;

	iMin.x = 0.0;
	iMin.y = 0.0;
	iMax.x = maxCoord.x;
	iMax.y = maxCoord.y;

	x = imageRect.origin.x;
	y = imageRect.origin.y;

	PSsetgray(0);
	NXRectFill(&imageRect);

	[self adjustSpeed: &delta.x minSpeed: MINSPEED maxSpeed: targetSpeed.x
	 pos: &x iMin: iMin.x iMax: iMax.x];
	[self adjustSpeed: &delta.y minSpeed: MINSPEED maxSpeed: targetSpeed.y
	 pos: &y iMin: iMin.y iMax: iMax.y];

	imageRect.origin.x = x;
	imageRect.origin.y = y;

	[self drawCube: 1.0];

	// Every once in an odd moon, change the targetSpeeds
	if (--xCount < 0)
	{
		xCount = random() % 1000;
		targetSpeed.x = randBetween(3,12);
	}
	if (--yCount < 0)
	{
		yCount = random() % 1000;
		targetSpeed.y = randBetween(3,12);
	}

	return self;
}

- initFrame:(NXRect *)frameRect
{
	[super initFrame: frameRect];

	imageRect.size.width = imageRect.size.height = CUBESIZE;

	return self;
}

- setImageConstraints
{
	[super setImageConstraints];

	if (imageRect.origin.x > maxCoord.x ||
		imageRect.origin.y > maxCoord.y)
	{
		imageRect.origin.x = randBetween(0, maxCoord.x);
		imageRect.origin.y = randBetween(0, maxCoord.y);
	}

	delta.x = targetSpeed.x = 6;
	delta.y = targetSpeed.y = 5;

	return self;
}

- setImage: image
{
	return self;
}

@end
